package com.xz.diagnosisOrder.service.impl;

import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.xz.common.annotation.DataScope;
import com.xz.common.core.domain.model.LoginUser;
import com.xz.common.exception.ServiceException;
import com.xz.common.utils.DateUtils;
import com.xz.common.utils.RedisCode;
import com.xz.common.utils.SecurityUtils;
import com.xz.diagnosisOrder.domain.DiagnosisOrder;
import com.xz.diagnosisOrder.domain.DiagnosisRefundOrder;
import com.xz.diagnosisOrder.domain.DiagnosisRefundOrderDetail;
import com.xz.diagnosisOrder.domain.DiagnosisTreatmentOrder;
import com.xz.diagnosisOrder.dto.DiagnosisRefundOrderConfirmDto;
import com.xz.diagnosisOrder.enums.PaymentStatusEnum;
import com.xz.diagnosisOrder.mapper.DiagnosisRefundOrderMapper;
import com.xz.diagnosisOrder.service.*;
import com.xz.diagnosisOrder.vo.DiagnosisRefundOrderListVo;
import com.xz.expense.enums.ExpenseBillBizTypeEnum;
import com.xz.expense.enums.ExpenseBillStatusEnum;
import com.xz.system.service.ISysDeptService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * 挂号/诊疗退费单Service业务层处理
 *
 * @author xz
 * @date 2024-03-27
 */
@Service
public class DiagnosisRefundOrderServiceImpl extends ServiceImpl<DiagnosisRefundOrderMapper, DiagnosisRefundOrder> implements IDiagnosisRefundOrderService {
  @Autowired
  private DiagnosisRefundOrderMapper diagnosisRefundOrderMapper;
  @Autowired
  private IDiagnosisRefundOrderDetailService diagnosisRefundOrderDetailService;
  @Autowired
  private ISysDeptService sysDeptService;
  @Autowired
  private IDiagnosisOrderService diagnosisOrderService;
  @Autowired
  private IDiagnosisTreatmentOrderService diagnosisTreatmentOrderService;
  @Autowired
  private IDiagnosisExpenseService diagnosisExpenseService;
  /**
   * 查询挂号/诊疗退费单
   *
   * @param id 挂号/诊疗退费单主键
   * @return 挂号/诊疗退费单
   */
  @Override
  public DiagnosisRefundOrder selectDiagnosisRefundOrderById(Long id) {
    return diagnosisRefundOrderMapper.selectDiagnosisRefundOrderById(id);
  }

  /**
   * 查询挂号/诊疗退费单列表
   *
   * @param diagnosisRefundOrder 挂号/诊疗退费单
   * @return 挂号/诊疗退费单
   */
  @Override
  public List<DiagnosisRefundOrder> selectDiagnosisRefundOrderList(DiagnosisRefundOrder diagnosisRefundOrder) {
    return diagnosisRefundOrderMapper.selectDiagnosisRefundOrderList(diagnosisRefundOrder);
  }

  @Override
  @DataScope(deptAlias = "d", userAlias = "u")
  public List<DiagnosisRefundOrderListVo> selectDiagnosisRefundOrderVoList(DiagnosisRefundOrder diagnosisRefundOrder) {
    return diagnosisRefundOrderMapper.selectDiagnosisRefundOrderVoList(diagnosisRefundOrder);
  }

  @Override
  @Transactional(rollbackFor = Exception.class)
  public void insertByOrder(DiagnosisOrder order) {
    DiagnosisRefundOrder refundOrder = initOrder(order);
    refundOrder.setOrderNo(RedisCode.getCode("ZLTF"));
    diagnosisRefundOrderMapper.insertDiagnosisRefundOrder(refundOrder);
    //添加详情数据
    diagnosisRefundOrderDetailService.insertByOrder(order, refundOrder);
    //开始创建费用管理中的记录
    diagnosisExpenseService.insertExpenseBill(refundOrder);
  }

  @Override
  @Transactional(rollbackFor = Exception.class)
  public void insertByOrder(List<DiagnosisTreatmentOrder> orders) {
    DiagnosisRefundOrder refundOrder = initOrder(orders);
    refundOrder.setOrderNo(RedisCode.getCode("ZLTF"));
    diagnosisRefundOrderMapper.insertDiagnosisRefundOrder(refundOrder);
    //添加详情数据
    diagnosisRefundOrderDetailService.insertByOrder(orders, refundOrder);
    //开始创建费用管理中的记录
    diagnosisExpenseService.insertExpenseBill(refundOrder);
  }

  @Override
  public DiagnosisRefundOrder initOrder(DiagnosisOrder order) {

    DiagnosisRefundOrder refundOrder = new DiagnosisRefundOrder();
    //填充基本信息
    refundOrder.setOrderType(1);
    refundOrder.setPatientId(order.getPatientId());
    refundOrder.setTotalRefundAmount(order.getCollectionAmount());
    //填充金额信息
    refundOrder.setTotalWalletPay(order.getWalletPay());
    refundOrder.setTotalPendingAmount(order.getPendingAmount());
    refundOrder.setStatus(PaymentStatusEnum.PENDING_REFUND.getStatus());
    //填充创建人信息
    LoginUser user = SecurityUtils.getLoginUser();
    refundOrder.setCreateBy(user.getUserId());
    refundOrder.setCreateByName(user.getUsername());
    refundOrder.setCreateTime(DateUtils.getNowDate());
    refundOrder.setTenantId(user.getTenantId());
    refundOrder.setDeptId(user.getDeptId());
    refundOrder.setDeptName(user.getUser().getDept().getDeptName());
    return refundOrder;
  }

  @Override
  public DiagnosisRefundOrder initOrder(List<DiagnosisTreatmentOrder> orders) {

    DiagnosisRefundOrder returnOrder = new DiagnosisRefundOrder();
    //填充基本信息
    returnOrder.setOrderType(2);
    returnOrder.setPatientId(orders.get(0).getPatientId());
    returnOrder.setStatus(PaymentStatusEnum.PENDING_REFUND.getStatus());
    //填充金额信息，计算总金额
    returnOrder.setTotalWalletPay(new BigDecimal(0));
    returnOrder.setTotalPendingAmount(new BigDecimal(0));
    returnOrder.setTotalRefundAmount(new BigDecimal(0));
    orders.forEach(order->{
      returnOrder.setTotalWalletPay(returnOrder.getTotalWalletPay().add(order.getWalletPay()));
      returnOrder.setTotalPendingAmount(returnOrder.getTotalPendingAmount().add(order.getPendingAmount()));
      returnOrder.setTotalRefundAmount(returnOrder.getTotalRefundAmount().add(order.getCollectionAmount()));
    });
    //填充创建人信息
    LoginUser user = SecurityUtils.getLoginUser();
    returnOrder.setCreateBy(user.getUserId());
    returnOrder.setCreateByName(user.getUsername());
    returnOrder.setCreateTime(DateUtils.getNowDate());
    returnOrder.setTenantId(user.getTenantId());
    returnOrder.setDeptId(user.getDeptId());
    returnOrder.setDeptName(user.getUser().getDept().getDeptName());
    return returnOrder;
  }

  @Override
  @Transactional(rollbackFor = Exception.class)
  public boolean cancelOrderById(Long id) {

    DiagnosisRefundOrder order = baseMapper.selectById(id);
    if(null == order){
      throw new ServiceException("操作失败，单据不存在");
    }
    // 查出数据后开始校验状态是否支持取消,只有到店,并且付款的数据，才能退单
    if (!PaymentStatusEnum.PENDING_REFUND.eq(order.getStatus())) {
      throw new ServiceException("操作失败，只有待退款状态的单据才能执行取消操作");
    }
    // 更新退费单数据
    LambdaUpdateWrapper<DiagnosisRefundOrder> wrapper = Wrappers.lambdaUpdate(DiagnosisRefundOrder.class);
    wrapper.set(DiagnosisRefundOrder::getStatus, PaymentStatusEnum.CANCELED.getStatus());
    wrapper.set(DiagnosisRefundOrder::getUpdateBy, SecurityUtils.getLoginUser().getUserId());
    wrapper.set(DiagnosisRefundOrder::getUpdateTime, DateUtils.getNowDate());
    wrapper.eq(DiagnosisRefundOrder::getId, id);
    boolean flag = update(wrapper);
    if (flag) {
      // 维护相关联的原订单数据
      updateRelatedOrdersByDetail(order,PaymentStatusEnum.PAID.getStatus());
      // 删除费用管理中的记录
      diagnosisExpenseService.delExpenseBill(order.getId(), ExpenseBillBizTypeEnum.TREATMENT_RETURN_ORDER.getType());
    }
    return flag;
  }

  @Override
  @Transactional(rollbackFor = Exception.class)
  public boolean confirmOrder(DiagnosisRefundOrderConfirmDto dto) {
    DiagnosisRefundOrder order = baseMapper.selectById(dto.getId());
    // 查出数据后开始校验状态是否支持取消,只有到店,并且付款的数据，才能退单
    if(null == order){
      throw new ServiceException("操作失败，单据不存在");
    }
    if (!PaymentStatusEnum.PENDING_REFUND.eq(order.getStatus())) {
      throw new ServiceException("操作失败，只有待退款状态的单据才能执行提交操作");
    }
    // 更新退费单数据
    LambdaUpdateWrapper<DiagnosisRefundOrder> wrapper = Wrappers.lambdaUpdate(DiagnosisRefundOrder.class);
    wrapper.set(DiagnosisRefundOrder::getStatus, PaymentStatusEnum.REFUNDED.getStatus());
    wrapper.set(DiagnosisRefundOrder::getRemark, dto.getVoucherRemark());
    wrapper.set(DiagnosisRefundOrder::getUpdateBy, SecurityUtils.getLoginUser().getUserId());
    wrapper.set(DiagnosisRefundOrder::getUpdateTime, DateUtils.getNowDate());
    wrapper.eq(DiagnosisRefundOrder::getId, dto.getId());
    boolean flag = update(wrapper);
    if (flag) {
      // 维护相关联的原订单数据
      updateRelatedOrdersByDetail(order,PaymentStatusEnum.REFUNDED.getStatus());
      // 确认费用管理中的记录
      int res = diagnosisExpenseService.confirmExpenseBill(dto);
      if(0 == res){
        throw new ServiceException("操作失败，更新费用记录失败");
      }
    }
    return flag;
  }

  /**
   * 维护相关联的原订单数据
   * @param order 退款单
   * @param status 状态 ExpenseBillBizTypeEnum
   */
  private void updateRelatedOrdersByDetail(DiagnosisRefundOrder order,Integer status) {
    // 开始维护原订单状态，先从详情数据中获取原订单集合
    List<DiagnosisRefundOrderDetail> details = diagnosisRefundOrderDetailService.selectDiagnosisRefundOrderDetailList(order.getId());
    if (!CollectionUtils.isEmpty(details)) {
      //过滤不合格数据，并且按状态分组
      Map<Integer, List<DiagnosisRefundOrderDetail>> detailsGroup = details.stream()
        .filter(detail -> null != detail.getBizId() && null != order.getOrderType())
        .collect(Collectors.groupingBy(DiagnosisRefundOrderDetail::getCostCategory));
      //根据订单类型维护原订单数据
      for(Integer type : detailsGroup.keySet()){
        List<Long> ids = detailsGroup.get(type).stream().map(DiagnosisRefundOrderDetail::getBizId).collect(Collectors.toList());
        if (type.equals(1)) {
          // 维护挂号单状态
          diagnosisOrderService.setPaymentStatusByBatchId(ids,status);
        } else if (order.getOrderType().equals(2)) {
          // 维护就诊单状态
          diagnosisTreatmentOrderService.setPaymentStatusByBatchId(ids,status);
        }
      }
    }
  }
}
